#include "TIM_Config.h"

/**
    ******************************************************************************
    * @file    Timer_Config.c
    * @brief   TIM4定时器配置及中断处理模块
    * @details 功能说明：
    *          - 提供高精度定时功能（默认1ms中断周期）
    *          - 通过参数化配置支持不同频率的中断触发
    *          - 维护全局毫秒计数器，用于超时检测或定时任务
    * @硬件依赖：
    *          - APB1总线时钟必须配置为36MHz（经倍频后为72MHz）
    *          - 使用TIM4定时器（通用定时器，挂载在APB1总线）
    ******************************************************************************
    */

/* 全局变量定义 --------------------------------------------------------------*/
volatile u16 ms_HcSR04_Count = 0;  
// 作用：累计TIM4的溢出次数，用于超声波传感器(Hc-SR04)的时间测量
// volatile修饰原因：
// 1. 在中断服务函数和主程序间共享，防止编译器优化导致读取缓存值
// 2. 确保原子性访问（16位操作在ARM Cortex-M3中是原子的）
// 注意：在多任务环境中需添加互斥保护（如关中断或使用信号量）

/**
    ******************************************************************************
    * @brief  NVIC中断控制器配置（私有函数）
    * @param  无
    * @retval 无
    * @配置说明：
    *         1. 优先级分组：Group2（2位抢占优先级，2位子优先级）
    *         2. TIM4中断配置：
    *            - 抢占优先级：2（共0-3级，数值越小优先级越高）
    *            - 子优先级：2（共0-3级）
    *            - 使能中断通道
    * @硬件操作：
    *         - 修改NVIC->IP[]寄存器设置中断优先级
    *         - 设置NVIC->ISER[]寄存器使能TIM4中断通道
    ******************************************************************************
    */
static void NVIC_Config(void)
{
    /* 设置NVIC优先级分组（影响所有中断） */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    // 分组含义：
    // - 2位抢占优先级（0-3）：高优先级可打断低优先级中断
    // - 2位子优先级（0-3）：同级抢占优先级中，子优先级高的先执行

    /* 配置TIM4中断通道 */
    NVIC_InitTypeDef NVIC_InitStructure = {
        .NVIC_IRQChannel                   = TIM4_IRQn,     // TIM4中断号（在stm32f10x.h中定义）
        .NVIC_IRQChannelPreemptionPriority = 0x02,          // 抢占优先级2（中等优先级）
        .NVIC_IRQChannelSubPriority        = 0x02,          // 子优先级2
        .NVIC_IRQChannelCmd                = ENABLE         // 使能中断通道
    };
    NVIC_Init(&NVIC_InitStructure);
}

/**
    ******************************************************************************
    * @brief  TIM4定时器初始化
    * @param  Freq_Up: 频率上升值（用于计算自动重装载值）
    * @param  Freq_Down: 频率下降值（用于计算自动重装载值）
    * @retval 无
    * @时钟配置：
    *         - 输入时钟：APB1总线时钟（默认36MHz，经倍频后为72MHz）
    *         - 预分频值：7200-1 → 计数频率=72MHz/(7200)=10kHz（100μs/计数）
    * @工作模式：
    *         - 向上计数模式：从0递增到自动重装载值，然后溢出并触发中断
    *         - 自动重装载值=(Freq_Up × 10000 / Freq_Down) - 1
    * @计算公式：
    *         中断周期 = (自动重装载值 + 1) × 100μs
    *         中断频率 = 10kHz / (自动重装载值 + 1)
    * @示例：
    *         TIM4_Config(1, 1) → 自动重装载值=9999 → 中断周期=1000ms（1Hz）
    *         TIM4_Config(1, 10) → 自动重装载值=999 → 中断周期=100ms（10Hz）
    ******************************************************************************
    */
void TIM4_Config(u32 Freq_Up, u32 Freq_Down)
{
    /* 使能TIM4时钟（APB1总线） */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

    /* 复位TIM4寄存器到默认值 */
    TIM_DeInit(TIM4);

    /* 时基单元配置 */
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = {
        .TIM_Prescaler         = 7200 - 1,              // 预分频值：7200-1（7200分频）
                                                         // 计数频率=72MHz/7200=10kHz（100μs/计数）
        .TIM_Period            = (Freq_Up * 10000 / Freq_Down) - 1,  // 自动重装载值
                                                         // 计算公式：(Freq_Up × 10000 / Freq_Down) - 1
        .TIM_ClockDivision     = TIM_CKD_DIV1,        // 时钟分频：不分频（不影响输入捕获）
        .TIM_CounterMode       = TIM_CounterMode_Up,  // 向上计数模式（0→ARR→0循环）
    };
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

    /* 清除潜在的更新中断标志 */
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);

    /* 使能更新中断 */
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

    /* 配置NVIC中断控制器 */
    NVIC_Config();

    /* 启动定时器 */
    TIM_Cmd(TIM4, ENABLE);
}

/**
    ******************************************************************************
    * @brief  TIM4中断服务函数（系统自动调用）
    * @param  无
    * @retval 无
    * @执行流程：
    *         1. 检查中断源是否为更新事件（计数器溢出）
    *         2. 清除中断标志位（必须操作，否则会重复触发中断）
    *         3. 递增毫秒计数器（ms_HcSR04_Count）
    * @注意事项：
    *         - 中断服务函数应保持短小精悍，避免阻塞操作
    *         - 实际执行时间约10-20μs（取决于系统时钟和操作复杂度）
    *         - 在RTOS环境中需考虑临界区保护（如使用原子操作或关中断）
    ******************************************************************************
    */
/*
void TIM4_IRQHandler(void)
{
    // 检查中断源是否为更新事件（计数器溢出）
    if (TIM_GetITStatus(TIM4, TIM_IT_Update)) {
        // 清除中断标志（写1清零）
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
        
        // 毫秒计数器递增（每次中断对应一定时间，取决于配置）
        ms_HcSR04_Count++;  // 若配置为1ms中断周期，则每次中断+1
    }
}
*/
